package com.wheel.autoconfigure.jackson.deserializer;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;


public class JacksonDeserializer4Date extends JsonDeserializer<Date> {

    private static final String[] patternsH = new String[]{"yyyy-MM-dd", "yyyy-MM-dd HH:mm", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm:ss.S", "yyyy-MM-dd HH:mm:ss.SSS"};
    private static final  String[] patternsHT = new String[]{"yyyy-MM-dd'T'HH:mm", "yyyy-MM-dd'T'HH:mm:ss", "yyyy-MM-dd'T'HH:mm:ss.S", "yyyy-MM-dd'T'HH:mm:ss.SSS", "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"};
    private static final  String[] patternsV = new String[]{"yyyy/MM/dd", "yyyy/MM/dd HH:mm", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm:ss.S", "yyyy/MM/dd HH:mm:ss.SSS"};
    private static final  String[] patternsVT = new String[]{"yyyy/MM/dd'T'HH:mm", "yyyy/MM/dd'T'HH:mm:ss", "yyyy/MM/dd'T'HH:mm:ss.S", "yyyy/MM/dd'T'HH:mm:ss.SSS", "yyyy/MM/dd'T'HH:mm:ss.SSS'Z'"};

    @Override
    public Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        Date targetDate = null;
        String originDate = p.getText().trim();
        if (!StringUtils.isEmpty(originDate)) {
            boolean hasT = originDate.indexOf("T") > -1;
            if (originDate.indexOf("-") > -1) {
                String[] patterns = hasT ? patternsHT : patternsH;
                targetDate = parseDate(originDate, patterns);
            } else if (originDate.indexOf("/") > -1) {
                String[] patterns = hasT ? patternsVT : patternsV;
                targetDate = parseDate(originDate, patterns);
            } else {
                try {
                    long longDate = Long.valueOf(originDate);
                    targetDate = new Date(longDate);
                } catch (NumberFormatException e) {
                }
            }
        }
        return targetDate;
    }

    @Override
    public Class<?> handledType() {
        return Date.class;
    }

    Date parseDate(String originDate, String... patterns) throws IOException {
        for (int i = patterns.length - 1; i >= 0; i--) {
            try {
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat(patterns[i], Locale.CHINA);
                simpleDateFormat.setTimeZone(TimeZone.getTimeZone("GMT+8"));
                return simpleDateFormat.parse(originDate);
            } catch (Exception e) {
            }
        }
        throw new IOException(String.format(
                "'%s' can not convert to type 'java.util.Date',just support timestamp(type of long) and following date format(%s)",
                originDate,
                Arrays.toString(patterns)));
    }
}